#pragma once
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Socket.hpp"
#include <functional>
#include <iostream>
#include <jsoncpp/json/reader.h>
#include <jsoncpp/json/value.h>
#include <jsoncpp/json/writer.h>
#include <memory>
#include <string>
#include "jsoncpp/json/json.h"
using namespace SocketModule;
// 这里实现的是一个通信的协议，也就是实现我们的序列化和反序列化
// 这里我们最好是用已经成熟的方案，比如之前我们使用过的jsonCpp库

// 请求模块
class Requset {
public:
    Requset() { }
    Requset(int x, int y, char oper) : _x(x), _y(y), _oper(oper) { }
    std::string Serialize() {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string ret = writer.write(root);
        return ret;
    }
    bool Deserialize(std::string& in) {
        Json::Value root;
        Json::Reader reader;
        bool n = reader.parse(in, root);
        if(n) {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return n;
    }
    ~Requset() {}
    int X() {
        return _x;
    }
    int Y() {
        return _y;
    }
    char Oper() {
        return _oper;
    }
private:
    int _x;
    int _y;
    char _oper;
};
// 响应模块
class Response {
public:
    Response() { }
    Response(int result, int code) : _result(result), _code(code) { }
    std::string Serialize() {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        std::string ret = writer.write(root);
        return ret;
    }
    bool Deserialize(std::string& in) {
        Json::Value root;
        Json::Reader reader;
        bool n = reader.parse(in, root);
        if(n) {
            _result = root["result"].asInt();
            _code = root["code"].asInt();
        }
        return n;
    }
    ~Response() { }
    void SetResult(int result) {
        _result = result;
    }
    void SetCode(int code) {
        _code = code;
    }
    void ShowResult() {
        std::cout << "计算机结果是：" << _result << "[" << _code << "]" << std::endl;
    }
private:
    int _result;
    int _code;
};
// 协议模块
const std::string sep = "\r\n";
using func_t = std::function<Response(Requset& req)>;
class Protocol {
public:
    Protocol() { }
    Protocol(func_t func) : _func(func) { }
    std::string Encode(const std::string& jsonstr) {
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep; // 封装的应用层报头
    }
    bool Decode(std::string& buffer, std::string* package) {
        auto pos = buffer.find(sep);
        if(pos == std::string::npos) {
            return false;
        }
        std::string strlen = buffer.substr(0, pos);
        int len = stoi(strlen);
        int length = len + strlen.size() + sep.size() * 2;
        if(length > buffer.size()) {
            return false;
        }
        *package = buffer.substr(pos + sep.size(), len);
        buffer.erase(0, length);
        return true;
    }
    void GetRequest(std::shared_ptr<Socket>& sock, InetAddr& client) {
        std::string buffer;
        while (1) {
            int n = sock->Recv(&buffer);
            if(n > 0) {
                std::cout << "---------------------request_buffer---------------------" << std::endl;
                std::cout << buffer << std::endl;
                std::cout << "---------------------**************---------------------" << std::endl;
                std::string jsonPackage;
                while (Decode(buffer, &jsonPackage)) {
                    LOG(LogLevel::DEBUG) << client.StringAddr() << "的请求：" << jsonPackage;
                    Requset req;
                    bool n = req.Deserialize(jsonPackage);
                    if(!n) {
                        continue;
                    }
                    Response resp = _func(req);
                    std::string jsonstr = resp.Serialize();
                    std::string sendstr = Encode(jsonstr);
                    sock->Send(sendstr);
                }
            }else if(n == 0) {
                LOG(LogLevel::INFO) << "client: " << client.StringAddr() << "退出了！";
                break;
            }else {
                LOG(LogLevel::WARNING) << "client: " << client.StringAddr() << "recv error";
                break;
            }
        }
    }
    bool GetResponse(std::shared_ptr<Socket>& client, std::string& buffer, Response* resp) {
        while (1) {
            int n = client->Recv(&buffer);
            if(n > 0) {
                std::string jsonPackage;
                while (Decode(buffer, &jsonPackage)) {
                    resp->Deserialize(jsonPackage);
                }
                return true;
            }else if(n == 0) {
                std::cout << "server quit!" << std::endl;
                return false;
            }else {
                std::cout << "recv error" << std::endl;
                return false;
            }
        }
    }
    std::string BuildRequestString(int x, int y, char oper) {
        Requset req(x, y, oper);
        std::string jsonReq = req.Serialize();
        return Encode(jsonReq);
    }
    ~Protocol() { }
private:
    func_t _func;
};